package mysql

import (
	"context"
	"errors"
	"github.com/zeromicro/go-zero/core/logx"
	"gorm.io/gen"
	"gorm.io/gen/field"
	"gorm.io/gorm"
	"gozero-demo/internal/constants"
	"gozero-demo/internal/model/dao/model"
	"gozero-demo/internal/model/dao/query"
	"gozero-demo/internal/svc"
	"gozero-demo/internal/types"
	"gozero-demo/internal/utils"
	"time"
)

type UserRepo struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
	q      *query.Query
}

func NewUserRepo(ctx context.Context, sCtx *svc.ServiceContext) *UserRepo {
	return &UserRepo{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: sCtx,
		q:      sCtx.Model,
	}
}

func (r *UserRepo) GetUserInfo(id int64) (*model.User, error) {
	m := r.svcCtx.Model.User
	res, err := m.WithContext(r.ctx).Debug().Where(m.ID.Eq(id)).Where(m.IsDeleted.Eq(0)).First()
	if err != nil {
		logx.WithContext(r.ctx).Errorf("Failed to get data by id: %v", err)
		return nil, err
	}
	return res, nil
}

func (r *UserRepo) GetUserCount(queryEqualConditions map[string]interface{}, queryMoreConditions map[string]interface{}) (int64, error) {
	m := r.svcCtx.Model.User
	queryEqualConditions["is_deleted"] = 0
	querys := m.WithContext(r.ctx).Debug()

	//基础查询条件
	querys = querys.Where(field.Attrs(queryEqualConditions))
	//更多查询条件
	if len(queryMoreConditions) > 0 {
		//todo your logic
	}

	return querys.Count()
}

func (r *UserRepo) GetUserListByGorm1(queryEqualConditions map[string]interface{}, queryMoreConditions map[string]interface{}, page, pageSize int) (list []*model.User, count int64, err error) {
	m := r.svcCtx.DB.Model(&model.User{})
	querys := m.WithContext(r.ctx).Debug()

	//基础查询条件
	queryEqualConditions["is_deleted"] = 0
	querys = querys.Where(queryEqualConditions)

	//更多查询条件
	if len(queryMoreConditions) > 0 {
		if queryMoreConditions["ids"] != nil {
			querys = querys.Where("id in ?", queryMoreConditions["ids"].([]int64))
		}
		if queryMoreConditions["user_name"] != "" {
			querys = querys.Where("user_name like ?", "%"+queryMoreConditions["user_name"].(string)+"%")
		}
		if queryMoreConditions["name"] != "" {
			querys = querys.Where("name like?", "%"+queryMoreConditions["name"].(string)+"%")
		}
		if queryMoreConditions["address"] != "" {
			querys = querys.Where("address like?", "%"+queryMoreConditions["address"].(string)+"%")
		}
		if queryMoreConditions["age_min"] != 0 {
			querys = querys.Where("age >=?", queryMoreConditions["age_min"].(int64))
		}
		if queryMoreConditions["age_max"] != 0 {
			querys = querys.Where("age <=?", queryMoreConditions["age_max"].(int64))
		}
		if queryMoreConditions["create_time_start"] != "" {
			// 将字符串类型的时间转换为 time.Time 类型
			createTimeStart, err := time.Parse("2006-01-02 15:04:05", queryMoreConditions["create_time_start"].(string))
			if err == nil {
				querys = querys.Where("create_time >=?", createTimeStart)
			}
		}
		if queryMoreConditions["create_time_end"] != "" {
			// 将字符串类型的时间转换为 time.Time 类型
			createTimeEnd, err := time.Parse("2006-01-02 15:04:05", queryMoreConditions["create_time_end"].(string))
			if err == nil {
				querys = querys.Where("create_time <=?", createTimeEnd)
			}
		}
	}

	querys.Limit(pageSize).Offset(page).Find(&list)
	querys.Count(&count)
	return list, count, nil
}

func (r *UserRepo) GetUserListByGorm2(queryEqualConditions map[string]interface{}, queryMoreConditions []Condition, page, pageSize int) (list []*model.User, count int64, err error) {
	m := r.svcCtx.DB.Model(&model.User{})
	querys := m.WithContext(r.ctx).Debug()

	//基础查询条件
	queryEqualConditions["is_deleted"] = 0
	querys = querys.Where(queryEqualConditions)

	//更多查询条件
	if len(queryMoreConditions) > 0 {
		querys = ApplyQueryConditions(querys, queryMoreConditions)
	}

	querys.Limit(pageSize).Offset(page).Find(&list)
	querys.Count(&count)
	return list, count, nil
}

func (r *UserRepo) GetUserListByGorm3(queryEqualConditions *model.User, queryMoreConditions []Condition, page, pageSize int) (list []*model.User, count int64, err error) {
	m := r.svcCtx.DB.Model(&model.User{})
	querys := m.WithContext(r.ctx).Debug()

	//基础查询条件
	queryEqualConditions.IsDeleted = 1
	querys = querys.Where(queryEqualConditions)

	//更多查询条件
	if len(queryMoreConditions) > 0 {
		querys = ApplyQueryConditions(querys, queryMoreConditions)
	}

	querys.Limit(pageSize).Offset(page).Find(&list)
	querys.Count(&count)
	return list, count, nil
}

func (r *UserRepo) GetUserListByGen1(queryEqualConditions map[string]interface{}, queryMoreConditions map[string]interface{}, page, pageSize int) (list []*model.User, count int64, err error) {
	m := r.svcCtx.Model.User
	querys := m.WithContext(r.ctx).Debug().Where(m.IsDeleted.Eq(0))

	//基础查询条件
	querys = querys.Where(field.Attrs(queryEqualConditions))

	//更多查询条件
	if len(queryMoreConditions) > 0 {
		if queryMoreConditions["ids"] != nil {
			querys = querys.Where(m.ID.In(queryMoreConditions["ids"].([]int64)...))
		}
		if queryMoreConditions["user_name"] != "" {
			querys = querys.Where(m.UserName.Like("%" + queryMoreConditions["user_name"].(string) + "%"))
		}
		if queryMoreConditions["age_min"] != 0 {
			querys = querys.Where(m.Age.Gte(queryMoreConditions["age_min"].(int64)))
		}
		if queryMoreConditions["age_max"] != 0 {
			querys = querys.Where(m.Age.Lte(queryMoreConditions["age_max"].(int64)))
		}
	}

	offset := (page - 1) * pageSize
	limit := pageSize
	res, count, err := querys.Order(m.ID.Desc()).FindByPage(offset, limit)
	if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
		logx.WithContext(r.ctx).Errorf("Failed to get list: %v", err)
		return nil, 0, err
	}
	return res, count, nil
}

// 构建查询用户数据的条件
func (r *UserRepo) BuildQueryUserListCondition(req *types.UserListRequest) (query.IUserDo, error) {
	m := r.svcCtx.Model.User
	querys := m.WithContext(r.ctx).Debug().Where(m.IsDeleted.Eq(0))
	if req.UserId > 0 {
		querys = querys.Where(m.UserID.Eq(req.UserId)) //eq查询
	}
	if req.Status > 0 {
		querys = querys.Where(m.Status.Eq(req.Status)) //eq查询
	}
	if req.Email != "" {
		querys = querys.Where(m.Email.Eq(req.Email)) //eq查询
	}
	if req.Ids != "" {
		idsSlice := utils.CommaSeparatedStringToInt64Slice(req.Ids)
		if len(idsSlice) > 0 {
			querys = querys.Where(m.ID.In(idsSlice...)) //in查询
		}
	}
	if req.UserName != "" {
		querys = querys.Where(m.UserName.Like("%" + req.UserName + "%")) //like查询
	}
	if req.AgeMin > 0 {
		querys = querys.Where(m.Age.Gte(req.AgeMin)) //>=查询
	}
	if req.AgeMax > 0 {
		querys = querys.Where(m.Age.Lte(req.AgeMax)) //<=查询
	}

	return querys, nil
}
func (r *UserRepo) GetUserListByGen2(req *types.UserListRequest) (list []*model.User, count int64, err error) {
	m := r.svcCtx.Model.User
	querys, err := r.BuildQueryUserListCondition(req)
	if err != nil {
		return nil, 0, err
	}

	limit := int(req.PageSize)
	offset := (int(req.Page) - 1) * limit
	res, count, err := querys.Order(m.ID.Desc()).FindByPage(offset, limit)
	if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
		logx.WithContext(r.ctx).Errorf("Failed to get list: %v", err)
		return nil, 0, err
	}
	return res, count, nil
}

func (r *UserRepo) GetUserCreateTimeMapByIds(Ids []int64) (map[int64]string, error) {
	if len(Ids) == 0 {
		return nil, nil
	}
	Ids = utils.RemoveDuplicatesInt64Slice(Ids)

	m := r.svcCtx.Model.User
	res, err := m.WithContext(r.ctx).Debug().Where(
		m.ID.In(Ids...),
		m.IsDeleted.Eq(0),
	).Find()
	if err != nil {
		logx.WithContext(r.ctx).Errorf("Failed to get create_time by ids: %v", err)
		return nil, err
	}

	mapData := make(map[int64]string, len(res))
	for _, v := range res {
		mapData[v.ID] = (v.CreateTime).Format("2006-01-02 15:04:05")
	}
	return mapData, nil
}

func (r *UserRepo) GetUserNameMapByIds(Ids []int64) (map[int64]string, error) {
	if len(Ids) == 0 {
		return nil, nil
	}
	Ids = utils.RemoveDuplicatesInt64Slice(Ids)

	m := r.svcCtx.Model.User
	res, err := m.WithContext(r.ctx).Debug().Where(
		m.ID.In(Ids...),
		m.IsDeleted.Eq(0),
	).Find()
	if err != nil {
		logx.WithContext(r.ctx).Errorf("Failed to get name by ids: %v", err)
		return nil, err
	}

	mapData := make(map[int64]string, len(res))
	for _, v := range res {
		mapData[v.ID] = v.Name
	}
	return mapData, nil
}

func (r *UserRepo) CreateUser(models *model.User) (*model.User, error) {
	m := r.svcCtx.Model.User
	err := m.WithContext(r.ctx).Debug().Create(models)
	if err != nil {
		logx.WithContext(r.ctx).Errorf("Failed to insert data: %v", err)
		return nil, err
	}
	return models, nil
}

func (r *UserRepo) UpdateUser(models *model.User, id int64, tx *query.QueryTx) (gen.ResultInfo, error) {
	q := r.svcCtx.Model
	if tx != nil {
		q = tx.Query
	}

	m := q.User
	res, err := m.WithContext(r.ctx).Debug().Where(m.ID.Eq(id)).Updates(models)
	if err != nil {
		logx.WithContext(r.ctx).Errorf("Failed to update data: %v", err)
		return res, err
	}
	return res, nil
}

func (r *UserRepo) UpdateUserV2(updateFields map[string]any, id int64, tx *query.QueryTx) (gen.ResultInfo, error) {
	if id <= 0 {
		return gen.ResultInfo{}, errors.New("id must be greater than 0")
	}
	if updateFields == nil || len(updateFields) == 0 {
		return gen.ResultInfo{}, errors.New("updateFields cannot be empty")
	}
	q := r.q
	if tx != nil {
		q = tx.Query
	}
	modelQuery := q.User
	res, err := modelQuery.WithContext(r.ctx).Debug().
		Where(modelQuery.ID.Eq(id)).
		Where(modelQuery.IsDeleted.Eq(constants.IsDeletedNo)).
		Updates(updateFields)
	if err != nil {
		logx.WithContext(r.ctx).Errorf("Failed to UpdateUserV2: %d, error: %v", id, err)
		return res, err
	}
	return res, nil
}

func (r *UserRepo) DeleteUser(id int64) (gen.ResultInfo, error) {
	m := r.svcCtx.Model.User
	res, err := m.WithContext(r.ctx).Debug().Where(m.ID.Eq(id)).Updates(&model.User{
		IsDeleted: 1,
	})
	if err != nil {
		logx.WithContext(r.ctx).Errorf("Failed to soft delete data: %v", err)
		return res, err
	}
	return res, nil
}

/*
func (r *UserRepo) ForeverDeleteUser(id int64) (gen.ResultInfo, error) {
	m := r.svcCtx.Model.User
	res, err := m.WithContext(r.ctx).Debug().Where(m.ID.Eq(id)).Delete()
	if err != nil {
		logx.WithContext(r.ctx).Errorf("Failed to hard delete data: %v", err)
		return res, err
	}
	return res, nil
}
*/

func (r *UserRepo) GetTotalUserCount() (int64, error) {
	m := r.svcCtx.Model.User
	count, err := m.WithContext(r.ctx).Debug().Count()
	if err != nil {
		logx.WithContext(r.ctx).Errorf("Failed to get user count: %v", err)
		return 0, err
	}
	return count, nil
}
